let UserDataManager = require('UserDataManager')
let BoardsManager = require('BoardsManager')
let Menu = require('Menu')
let GameWinBoard = require('GameWinBoard')
let UnlockCarBoard = require('UnlockCarBoard')
let GameDataManager = require('GameDataManager')
let AudioManager = require('AudioManager')
let WX = require('WX')
let MiniP = require('MiniP')

let Main = cc.Class({
  extends: cc.Component,

  properties: {
    Car: cc.Prefab,
    CashLine: cc.Prefab,
    whiteShine: cc.Node,
    activeCashLines: cc.Node,
    activeCars: cc.Node,
    howToPlay: cc.Node,
    settingBoard: cc.Node,
    chapterLine: cc.Node,
    gameWinBoard: cc.Node,
    unlockCarBoard: cc.Node,
    cashDollar: cc.Node,

    Balls: cc.Prefab,
    Basketball: cc.Prefab,
    TailGus: cc.Prefab,

    FireTruck: cc.Prefab,
    Train: cc.Prefab,
    TrainTip: cc.Prefab,

    miniP: cc.Node,

    curBoard: cc.Node,

    retrieveBoard: cc.Node,
  },

  statics: {
    instance: null
  },

  ctor () {
    if (!Main.instance) {
      Main.instance = this
    }
  },

  onLoad () {
    console.log('Main-onload')
    this.curBoard.zIndex = -3;
    UserDataManager.loadUserData()
    if (UserDataManager.getUserData().newUser) {
      this.showHowToPlay()
      UserDataManager.saveUserData2('newUser', false)
      Menu.instance.hide()
    } else {
      Menu.instance.open()
    }

    WX.login()
    cc.director.getCollisionManager().enabled = true
    cc.director.getPhysicsManager().enabled = true
    this.setGravity(0)

    this.nextBoardSpriteFrame = null;

    this.speedReduction = 0
    this.carOutIndex = 0
    this.camera = this.node.getChildByName('camera')
    this.isGameStart = false
    this.cashDollar.active = false

    this.carPool = new cc.NodePool()
    this.cashLinePool = new cc.NodePool()
    this.carArr = []
    this.cashLineArr = []
    this.trains = []
    this.fireTrucks = []

    this.preCarPoint = {}

    this.updateBoard()
    this.updateChapterLine(0)
  },

  gameStart () {
    console.log('Main-gameStart')
    this.setGravity(0)

    // 初始化参数
    this.hadRetrieve = false;
    this.firstPass = true
    this.cashDollar.active = false
    this.isGameStart = true
    this.hadCollision = false
    this.chapterExp = 0
    this.gameStartTime = new Date().getTime()
    MiniP.instance.inBoard(this.boardLevel)

    this.camera.getComponent(cc.Camera).zoomRatio = 1
    this.camera.x = 0
    this.camera.y = 0

    let chapterLevel = UserDataManager.getUserData().chapterLevel
    if (chapterLevel === this.preChapterLevel) {
      this.speedReduction += 5
    } else {
      this.preChapterLevel = chapterLevel
      this.speedReduction = 0
    }
    // console.log('this.speedReduction', this.speedReduction)
    // if (
    //   chapterLevel > 2 &&
    //   chapterLevel % 5 === 0 &&
    //   WX.shareEnable &&
    //   this.hadShareChapterLevel !== chapterLevel
    // ) {
    //   WX.share(
    //     () => {
    //       this.hadShareChapterLevel = chapterLevel
    //       Menu.instance.hide()
    //       this.newScene()
    //     },
    //     () => {
    //       console.log('Fail to share')
    //     }
    //   )
    // } else {
      Menu.instance.hide()
      this.newScene()
    // }

    this.chapterLine
      .getChildByName('rightCircleMask')
      .getChildByName('color').active = false
  },

  newScene () {
    console.log('Main-newScene')
    this.clearAllSceneObjects()
    this.clearAllSpecial()
    this.specialBoard()
    this.createCashLines()
    this.updateChapterLine(0)
  },



  clearAllSceneObjects () {
    console.log('Main-clearAllSceneObjects')
    if (this.balls) {
      this.balls.removeFromParent()
    }
    while (this.cashLineArr.length) {
      if(this.cashLinePool){
        this.cashLinePool.put(this.cashLineArr.pop())
      }
    }
    while (this.carArr.length) {
      if(this.carPool){
        this.carPool.put(this.carArr.pop())
      }
    }
  },
  clearAllSpecial () {
    console.log('Main-clearAllSpecial')
    for (let train of this.trains) {
      train.getComponent('Train').stop()
    }
    for (let fireTruck of this.fireTrucks) {
      fireTruck.getComponent('FireTruck').stop()
    }
    this.trains = []
    this.fireTrucks = []
  },

  updateBoard () {
    console.log('Main-updateBoard')
    this.setGravity(0)
    this.chapterLevel = UserDataManager.getUserData().chapterLevel
    this.boardLevel = this.chapterLevel % 41

    this.boardData = BoardsManager.getBoardData(this.boardLevel)

    this.carInterval = 240 - this.chapterLevel * 0.1
    if (this.boardData.carOutRate) this.carInterval /= this.boardData.carOutRate
    this.carInterval = Math.round(this.carInterval)
    if (this.carInterval < 100) this.carInterval = 100

    if (this.boardData.agentBoardLevel >= 0) {
      this.boardLevel = this.boardData.agentBoardLevel
      this.boardData = BoardsManager.getBoardData(this.boardLevel)
    }

    if(this.boardLevel !== 0 && this.nextBoardSpriteFrame){
      this.curBoard.getComponent(cc.Sprite).spriteFrame = this.nextBoardSpriteFrame;
      this.nextBoardSpriteFrame = null;
    }else{
      cc.loader.loadRes(
        'boards/board' + this.boardLevel,
        cc.SpriteFrame,
        (err, spriteFrame) => {
          if (err) {
            cc.error(err.message || err)
            return
          }
          this.curBoard.getComponent(cc.Sprite).spriteFrame = spriteFrame;
        }
      )
    }

    let nextBoardLevel = (this.boardLevel + 1) % 41;
    cc.loader.loadRes(
      'boards/board' + nextBoardLevel,
      cc.SpriteFrame,
      (err, spriteFrame) => {
        if (err) {
          cc.error(err.message || err)
          return
        }
        this.nextBoardSpriteFrame = spriteFrame;
      }
    )
  },

  specialBoard () {
    console.log('Main-specialBoard')
    if (this.boardData.balls) {
      if (this.balls) this.balls.removeFromParent()
      let balls = cc.instantiate(this.Balls)
      this.node.addChild(balls)
      this.balls = balls
      this.balls.zIndex = -1
    }

    if (this.boardData.fireTruckSetting) {
      let setting = this.boardData.fireTruckSetting
      let fireTruck = cc.instantiate(this.FireTruck)
      this.node.addChild(fireTruck)
      fireTruck.getComponent('FireTruck').init(setting)
      fireTruck.zIndex = -1
      this.fireTrucks.push(fireTruck)
    }

    if (this.boardData.trainSetting) {
      let trainSetting = this.boardData.trainSetting
      for (let i = 0; i < trainSetting.length; i++) {
        let distance = 800
        let r = (Math.PI / 180) * -trainSetting[i].rota
        let dx = distance * Math.cos(r)
        let dy = distance * Math.sin(r)

        let trainTip = cc.instantiate(this.TrainTip)
        trainTip.rotation = trainSetting[i].rota
        trainTip.x = trainSetting[i].x + dx
        trainTip.y = trainSetting[i].y + dy
        trainTip.zIndex = -1
        this.node.addChild(trainTip)

        let train = cc.instantiate(this.Train)
        train.zIndex = -1
        train.getComponent('Train').init(trainSetting[i], trainTip)
        this.node.addChild(train)
        this.trains.push(train)
      }
    }
  },

  createCashLines () {
    // console.log('Main-createCashLines')
    this.activeCashLines.zIndex = -2
    for (let cashLine of this.boardData.cashLines) {
      console.log(cashLine)
      let theCashLine
      if (this.cashLinePool.size() > 0) {
        theCashLine = this.cashLinePool.get()
      } else {
        theCashLine = cc.instantiate(this.CashLine)
      }

      theCashLine.active = true
      theCashLine.x = cashLine.x
      theCashLine.y = cashLine.y

      let cashLineLongContent = theCashLine.getChildByName(
        'cashLineLongContent'
      )
      let cashLineLongInactive = cashLineLongContent.getChildByName(
        'cashLineLongInactive'
      )
      let cashLineLong = cashLineLongContent.getChildByName('cashLineLong')

      if (!theCashLine._iniWidth) {
        theCashLine._iniWidth = cashLineLongInactive.width
      }

      cashLineLongContent.rotation = cashLine.rota
      let BoxCollider = cashLineLongContent.getComponent(cc.BoxCollider)
      let _width = theCashLine._iniWidth * cashLine.scaleX
      BoxCollider.size.width = _width
      cashLineLongInactive.width = _width
      cashLineLong.width = _width

      cashLineLongContent._code = cashLine._code
      this.activeCashLines.addChild(theCashLine)
      this.cashLineArr.push(theCashLine)
    }
  },

  updateChapterLine (addExp) {
    let left = this.chapterLine.getChildByName('leftCircleMask')
    let right = this.chapterLine.getChildByName('rightCircleMask')

    left.getChildByName('color').active = true
    left.getChildByName('txt').getComponent(cc.Label).string =
      this.chapterLevel + 1
    right.getChildByName('txt').getComponent(cc.Label).string =
      this.chapterLevel + 2

    let chapterPassExp = GameDataManager.getChapterPassExp(this.chapterLevel)
    this.chapterExp += addExp

    this.cashDollar.getComponent(cc.Label).string = this.chapterExp
    this.cashDollar.stopAllActions()
    this.cashDollar.scale = 1.5
    this.cashDollar.opacity = 0
    this.cashDollar.runAction(cc.spawn(cc.scaleTo(0.5, 1), cc.fadeTo(0.5, 255)))

    let rate = this.chapterExp / chapterPassExp
    if (rate >= 1) {
      rate = 1
      this.gameWin()
      right.getChildByName('color').active = true
    }
    this.chapterLine.getChildByName('line').scaleX = rate
  },

  getWeather (chapterLevel) {
    let sunColor = new cc.Color(255, 255, 255)
    let midNightColor = new cc.Color(201, 146, 159)
    let nightColor = new cc.Color(122, 128, 156)

    if (chapterLevel < 10) return sunColor
    let d = chapterLevel % 9
    if (d < 3) {
      return sunColor
    } else if (d < 6) {
      return midNightColor
    } else {
      return nightColor
    }
  },

  createOppositeCars () {
    let boardStartPoints = this.boardData.startPoints
    let point
    let f = 3
    while (f > 0) {
      f--
      point =
        boardStartPoints[Math.floor(Math.random() * boardStartPoints.length)]
      if (point._code !== this.preCarPoint._code) break
    }
    this.preCarPoint = point
    console.log('Main-createCar point._code:', point._code)

    let oppositePoint = boardStartPoints[point.opposite - 1];
    let sendOppositeCar = point.rota !== oppositePoint.rota && Math.random() > 0.1;
    
    setTimeout(() => {
      let speedIncreaseRate = 1;
      // if(!sendOppositeCar){
      //   let r = Math.random();
      //   if(r<0.05){
      //     speedIncreaseRate = 10;
      //   }else if(r<0.3){
      //     speedIncreaseRate = 3;
      //   }
      // }
      this.createCar(point,speedIncreaseRate)
        .getComponent('Car')
        .move()
    }, point.delay * 800 + Math.random() * 400)


    if (sendOppositeCar) {
      setTimeout(() => {
        this.createCar(oppositePoint)
          .getComponent('Car')
          .move()
      }, oppositePoint.delay * 800 + Math.random() * 400)
    }
  },

  createCar (point,speedIncreaseRate) {
    let carLevel = Math.floor(
      Math.random() * UserDataManager.getUserData().carLevel
    )
    let car
    if (this.carPool.size() > 0) {
      car = this.carPool.get()
    } else {
      car = cc.instantiate(this.Car)
    }

    let speedIncrementer = 0
    if (this.boardData.speedIncrementer) {
      speedIncrementer = this.boardData.speedIncrementer - this.speedReduction
      if (speedIncrementer < 0) speedIncrementer = 0
    }
    car.getComponent('Car').setPoint(point, this.chapterLevel, speedIncrementer, speedIncreaseRate)
    for (let c of car.children) c.active = false
    car.getChildByName('carPartical').active = true

    let theCar = car.getChildByName('car_' + carLevel)
    theCar.active = true
    car.width = theCar.width * 1.2
    car.height = theCar.height * 1.2
    car.theCar = theCar
    car.carLevel = carLevel

    let colliderPoints = car.getComponent(cc.PhysicsPolygonCollider).points
    // 修改顺序: 第3象限 -> 第4象限 -> 第1象限 -> 第2象限， 否则会导致碰撞线交错而报错
    let theCarWidth = theCar.width / 2.2
    let theCarHeight = theCar.height / 2.2

    colliderPoints[0].x = -theCarWidth
    colliderPoints[0].y = -theCarHeight
    colliderPoints[1].x = theCarWidth
    colliderPoints[1].y = -theCarHeight
    colliderPoints[2].x = theCarWidth
    colliderPoints[2].y = theCarHeight
    colliderPoints[3].x = -theCarWidth
    colliderPoints[3].y = theCarHeight

    let rigidbody = car.getComponent(cc.RigidBody)
    rigidbody.enabledContactListener = true
    this.activeCars.addChild(car)
    this.carArr.push(car)

    return car
  },

  setGravity (g) {
    cc.director.getPhysicsManager().gravity = cc.v2(0, -32 * g)
  },

  makeCollision (r1, r2) {
    console.log('Main-makeCollision')
    if (this.hadCollision) return
    this.hadCollision = true

    this.camera.getComponent(cc.Camera).zoomRatio = 1.2
    this.whiteShine.active = true
    this.whiteShine.runAction(
      cc.sequence(
        cc.fadeTo(0.1, 150),
        cc.fadeTo(0.1, 40),
        cc.callFunc(() => {
          this.whiteShine.active = false
        })
      )
    )
    let theX = 0

    let theY = 0
    if (r1 < 90 || r2 < 90) {
      theX = -90
    } else if (r1 < 180 || r2 < 180) {
      theY = 90
    } else if (r1 < 270 || r2 < 270) {
      theX = 90
    } else {
      theY = -90
    }

    let move = cc.moveTo(2, theX, theY)
    move.easing(cc.easeOut(3))
    this.camera.runAction(move)
  },

  slowDownAllCars () {
    console.log('Main-slowDownAllCar')
    for (let car of this.carArr) car.getComponent('Car').slowDown()
  },

  gameWin () {
    console.log('Main-gameWin')
    this.isGameStart = false

    let passTime = new Date().getTime() - this.gameStartTime
    WX.ald.sendEventChapterPass(this.chapterLevel, passTime)

    UserDataManager.saveUserData2('chapterLevel', this.chapterLevel + 1)

    // cc.director.getPhysicsManager().gravity = cc.v2((Math.random() > 0.5 ? 1 : -1) * 50, (Math.random() > 0.5 ? 1 : -1) * 50);
    this.slowDownAllCars()

    setTimeout(() => {
      // UnlockCarBoard.instance.open({
      //   carLevel: UserDataManager.getUserData().carLevel,
      //   chapterExp: this.chapterExp
      // });
      if(this.chapterLevel > 2 && this.chapterLevel % 3 === 0){
        UnlockCarBoard.instance.open({
          carLevel: UserDataManager.getUserData().carLevel,
          chapterExp: this.chapterExp
        });
      }else{
        GameWinBoard.instance.open({
          chapterExp: this.chapterExp
        });
      }
    }, 1000)
  },

  gameOver () {
    console.log('Main-gameOver')
    this.isGameStart = false
    UserDataManager.saveUserData2(
      'dollar',
      UserDataManager.getUserData().dollar + this.chapterExp
    )

    this.camera.getComponent(cc.Camera).zoomRatio = 1
    this.camera.x = 0
    this.camera.y = 0

    if(this.hadRetrieve){
      Menu.instance.open()
    }else{
      this.retrieveBoard.getComponent("RetrieveBoard").open();
    }
  },
  
  retrieve(){
    console.log("Main-retrieve")

    let makeRetrieve = ()=>{
      console.log("Main-retrieve-makeRetrieve")
      this.hadCollision = false
      this.isGameStart = true;
      this.hadRetrieve = true;
      this.camera.getComponent(cc.Camera).zoomRatio = 1
      this.camera.x = 0
      this.camera.y = 0
  
      this.clearAllSceneObjects()
      this.clearAllSpecial()
      this.specialBoard()
      this.createCashLines()
      this.retrieveBoard.getComponent("RetrieveBoard").close();
    };

    console.log("WX.shareEnable",WX.shareEnable);
    if(WX.shareEnable){
      WX.share(()=>{
        console.log("分享成功");
        makeRetrieve();
      },()=>{
        console.log("分享失败");
      })
    }else{
      WX.watchVideoAD(()=>{
        makeRetrieve();
      });
    }
  },

  showHowToPlay () {
    this.howToPlay.active = true
    this.howToPlay.zIndex = 10000
  },
  hideHowToPlay () {
    this.howToPlay.active = false
    if (!this.isGameStart) {
      Menu.instance.open()
    }
  },

  showSettingBoard () {
    this.settingBoard.active = true
  },
  hideSettingBoard () {
    this.settingBoard.active = false
  },

  start () {},

  update (dt) {
    // console.log(this.isGameStart, this.carOutIndex, this.carInterval)
    if(this.isGameStart){
      if(this.carOutIndex % this.carInterval === 0){
        this.createOppositeCars()
      }
      this.carOutIndex++
    }
  }
})
